﻿using System;
using System.Globalization;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;
using Scommesse.Model;
using Scommesse.Utility;

namespace Scommesse.Persistence
{
    public static class DataLoader
    {

        

        public static Palinsesto LoadPalinsestoFromFile()
        {
            Palinsesto palinsesto = Palinsesto.GetPalinsesto();
            var palXml = new XmlDocument();
            // se non riesce il caricamento del palinsesto
            try
            {
                palXml.Load("palinsesto.pal");
            }
            // salva un nuovo file di palinsesto su disco
            catch
            {
                DataSaver.SavePalinsestoOnFile(palinsesto);
            }
            var rootElement = (XmlElement) palXml.SelectSingleNode("Palinsesto/Categorie");
            if (rootElement != null)
            {
                foreach (XmlElement childElement in rootElement.SelectNodes("categoria"))
                {
                    LoadCategoria(childElement, palinsesto);
                }
            }
            return palinsesto;
        }

        private static void LoadCategoria(XmlElement categoriaElement, Palinsesto palinsesto)
        {
            ICategoria categoria = palinsesto.AddCategoria(categoriaElement.GetAttribute("nome"));
            var rootElement = (XmlElement) categoriaElement.SelectSingleNode("Tipologie");
            if (rootElement != null)
                foreach (XmlElement childElement in rootElement.SelectNodes("tipologia"))
                {
                    categoria.Tipologie.Add(
                        StringValueAttribute.GetEnumByStringValueAttribute<Tipologia>(childElement.GetAttribute("nome")),
                        Type.GetType(childElement.GetAttribute("tipo")));
                }
            rootElement = (XmlElement) categoriaElement.SelectSingleNode("Competizioni");
            if (rootElement != null)
                foreach (XmlElement childElement in rootElement.SelectNodes("competizione"))
                {
                    LoadCompetizione(childElement, categoria);
                }
        }

        private static void LoadCompetizione(XmlElement competizioneElement, ICategoria categoria)
        {
            ICompetizione comp = categoria.AddCompetizione(competizioneElement.GetAttribute("nome"));
            var rootElement = (XmlElement) competizioneElement.SelectSingleNode("Eventi");
            if (rootElement != null)
                foreach (XmlElement childElement in rootElement.SelectNodes("evento"))
                {
                    LoadEvento(childElement, comp);
                }
        }

        private static void LoadEvento(XmlElement eventoElement, ICompetizione competizione)
        {
            Guid id;
            // si introduce questo controllo per convertire gli eventi dei vecchi palinsesti (senza guid), 
            // assegnandone uno nuovo in automatico (che verrà poi persistito automaticamente)
            try
            {
                id = new Guid(eventoElement.GetAttribute("id"));
            }
            catch (FormatException)
            {
                id = Guid.NewGuid();
            }
            string compA = eventoElement.GetAttribute("competitoreA");
            string compB = eventoElement.GetAttribute("competitoreB");
            DateTime dataOra = DateTime.Parse(eventoElement.GetAttribute("dataOra"), new CultureInfo("it-IT", true));
            var stato =
                StringValueAttribute.GetEnumByStringValueAttribute<StatoEvento>(
                    eventoElement.GetAttribute("stato"));

            IEvento evento = competizione.AddEvento(id, compA, compB, dataOra, stato);

            if (stato.Equals(StatoEvento.Terminato))
            {
                evento.SetPunteggi(Convert.ToInt32(eventoElement.GetAttribute("punteggioA")),
                                   Convert.ToInt32(eventoElement.GetAttribute("punteggioB")));
            }
        }

        public static IBetCard LoadBetCardFromFile(String codiceTessera)
        {
            var fs = new FileStream(codiceTessera + ".betCard", FileMode.Open);
            var bf = new BinaryFormatter();
            IBetCard betCard = (IBetCard) bf.Deserialize(fs);
            fs.Close();
            return betCard;
        }
    }
}